﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows;
using AutoLoL.Entities;
using AutoLoL.Logic.Automation;
using AutoLoL.Logic.Exceptions;
using AutoLoL.Shared;
using Point = System.Drawing.Point;

namespace AutoLoL.Logic.Windows
{
    public enum MASTERY_WINDOWS { None, ChampionSelect, UserProfile };

    public class ClientWindow : BaseWindow
    {
        #region Pixels
        private static readonly Dictionary<Point, Color> PROFILE_PIXELS = new Dictionary<Point, Color>()
        {
            { new Point(130, 710), Color.FromArgb(0xC9B173) }, // Brown area bottom left 
            { new Point(785, 185), Color.FromArgb(0xF6E7BD) }, // Mastery tab
            { new Point(695, 470), Color.FromArgb(0x00B7B8) }, // Blue tree center
            { new Point(1120, 700), Color.FromArgb(0x030904) } // Green tree bottom right
        };

        private static readonly Dictionary<Point, Color> CHAMP_SELECT_PIXELS = new Dictionary<Point, Color>()
        {
            { new Point(135, 630), Color.FromArgb(0xC9B173) }, // Brown area bottom left
            { new Point(1040, 140), Color.FromArgb(0xEDECCA) }, // Top bar center
            { new Point(707, 383), Color.FromArgb(0x00BCBB) }, // Blue tree center
            { new Point(1125, 625), Color.FromArgb(0x030904) } // Green tree bottom right
        };

        private static readonly Dictionary<Point, Color> LOGIN_PIXELS = new Dictionary<Point, Color>()
        {
            { new Point(875, 165), Color.FromArgb(0xecd33b) }, // L from logo
            { new Point(1075, 420), Color.FromArgb(0x8b8b8b) }, // Login button
            { new Point(1200, 80), Color.FromArgb(0x130000) } // Top right area
        };
        #endregion

        private static readonly Point USER_PROFILE_RETURN = new Point(220, 415);
        private static readonly Point CHAMPION_SELECT_RETURN = new Point(225, 335);

        private static readonly string[] LOL_WINDOW_NAMES = new string[] { "PVP.net Client", "PVP.net-Client", "Client Pvp.net", "PVP.net Клиент", "Клиент PVP.net", "Cliente PVP.net" };
        private const string LOL_CLASS_NAME = "ApolloRuntimeContentWindow";

        public bool DEBUG = false;

        public ClientWindow()
        {
            foreach (string window in LOL_WINDOW_NAMES)
            {
                Handle = Win32.FindWindow(LOL_CLASS_NAME, window);

                if (Handle != IntPtr.Zero)
                {
                    break;
                }
            }

            if (Handle == IntPtr.Zero)
            {
                throw new WindowNotFoundException("Client");
            }
        }

        public Point GetReturnPointLocation(MASTERY_WINDOWS targetWindow)
        {
            double ratio = this.ClientRectangle.Width / Constants.BASE_CLIENT_WIDTH;

            if (targetWindow == MASTERY_WINDOWS.UserProfile)
            {
                int pixelX = (int)Math.Round((double)USER_PROFILE_RETURN.X * ratio);
                int pixelY = (int)Math.Round((double)USER_PROFILE_RETURN.Y * ratio);
                Point result = new Point(pixelX, pixelY);

                result.Offset(this.Position);

                return result;
            }
            else if (targetWindow == MASTERY_WINDOWS.ChampionSelect)
            {
                int pixelX = (int)Math.Round((double)CHAMPION_SELECT_RETURN.X * ratio);
                int pixelY = (int)Math.Round((double)CHAMPION_SELECT_RETURN.Y * ratio);
                Point result = new Point(pixelX, pixelY);

                result.Offset(this.Position);

                return result;
            }

            return Point.Empty;
        }

        public Point GetMasteryLocation(MASTERY_WINDOWS targetWindow, MasteryValue mastery)
        {
            int startX, startY, columnW, rowH, gapW;

            if (targetWindow == MASTERY_WINDOWS.UserProfile)
            {
                startX = 392;
                startY = 285;
                columnW = 62;
                rowH = 72;
                gapW = 276;
            }
            else if (targetWindow == MASTERY_WINDOWS.ChampionSelect)
            {
                startX = 402;
                startY = 204;
                columnW = 62;
                rowH = 72;
                gapW = 276;
            }
            else
            {
                return Point.Empty;
            }

            Point result = new Point(startX, startY);
            result.X += mastery.Column * columnW;
            result.Y += mastery.Row * rowH;

            switch (mastery.MasteryTree.Name)
            {
                case "Defense":
                    result.X += (int)gapW;
                    break;
                case "Utility":
                    result.X += (int)gapW * 2;
                    break;
                default:
                    break;
            }

            double ratio = this.ClientRectangle.Width / Constants.BASE_CLIENT_WIDTH;
            result.X = (int)Math.Round((double)result.X * ratio);
            result.Y = (int)Math.Round((double)result.Y * ratio);

            result.Offset(this.Position);

            return result;
        }

        public bool IsMasteriesOpen(MASTERY_WINDOWS targetWindow)
        {
            if (targetWindow == MASTERY_WINDOWS.UserProfile)
            {
                return CheckPixels(0.96, PROFILE_PIXELS);
            }
            else if (targetWindow == MASTERY_WINDOWS.ChampionSelect)
            {
                return CheckPixels(0.93, CHAMP_SELECT_PIXELS);
            }

            return false;
        }

        public bool IsLoginWindowOpen()
        {
            return CheckPixels(0.96, LOGIN_PIXELS);
        }

        private bool CheckPixels(double matchRequired, Dictionary<Point, Color> pixels)
        {
            if (!this.IsForegroundWindow)
            {
                return false;
            }

            double ratio = this.ClientRectangle.Width / Constants.BASE_CLIENT_WIDTH;

            foreach (Point point in pixels.Keys)
            {
                // Calculate the actual location of the point
                int pixelX = (int)Math.Round((double)point.X * ratio);
                int pixelY = (int)Math.Round((double)point.Y * ratio);

                // Check the pixel
                Color color = this.GetPixelColor(pixelX, pixelY);
                double match = CompareColors(color, pixels[point]);

                if (DEBUG)
                {
                    Console.WriteLine(pixelX + "::" + pixelY + " = " + match + " (" + color + " = " + pixels[point] + ")");
                }

                if (match < matchRequired)
                {
                    return false;
                }
            }

            return true;
        }

        public double CompareColors(Color a, Color b)
        {
            return 1.0 - (double)(Math.Abs(a.R - b.R) + Math.Abs(a.G - b.G) + Math.Abs(a.B - b.B)) / (255.0 * 3);
        }
    }
}
